package cloud.maque.common.logaop;

import com.alibaba.fastjson.JSON;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.apm.toolkit.trace.ActiveSpan;
import org.apache.skywalking.apm.toolkit.trace.TraceContext;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
 * 全局的controller拦截，把日志信息发给SkyWalking
 */
@Slf4j
@Aspect
@Component
public class ControllerLogAspect {
    @Pointcut("execution(public * cloud.maque..controller..*.*(..))")
    public void apiPointcut() {
    }

    @Around("apiPointcut()")
    public Object executeFaceAspect(ProceedingJoinPoint joinPoint) throws Throwable {
        Object returnObj = null;
        Object[] parameters = joinPoint.getArgs();
        try {
            returnObj = joinPoint.proceed();
        } catch (Exception e) {
            log.error("SkyWalking aspect catch exception {}", TraceContext.traceId(), e);
            //创建新的数据标签
            ActiveSpan.tag("异常", e.toString());
            throw e;
        } finally {
            if (parameters != null && parameters.length > 0) {
                for (int i = 0; i < parameters.length; i++) {
                    try {
                        Object nowObj = parameters[i];
                        if (nowObj instanceof HttpServletRequest) {
                            continue;
                        }
                        //创建新的数据标签
                        ActiveSpan.tag("入参" + i, replaceLog(JSON.toJSONString(nowObj)));
                    } catch (Exception ignore) {
                    }
                }
            }
            if (returnObj != null) {
                try {
                    //创建新的数据标签
                    ActiveSpan.tag("出参", replaceLog(JSON.toJSONString(returnObj)));
                } catch (Exception ignore) {
                }
            }
        }
        return returnObj;
    }

    public static String replaceLog(String logStr) {
        // 格式化日志内容，避免日志过大
        if (String.valueOf(logStr).length() > 8192) {
            return logStr.substring(0, 8192) + "...";
        }
        return logStr;
    }
}